package com.tony.server.service;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.jdom2.JDOMException;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tony.easymvc.core.ProjectGenerator;
import com.tony.easymvc.core.TableUtils;
import com.tony.easymvc.core.bean.ProjectContext;
import com.tony.easymvc.core.bean.ProjectModel;
import com.tony.easymvc.mapper.BizDbMapper;
import com.tony.easymvc.mapper.DbInfoMapper;
import com.tony.easymvc.mapper.HtmlOperationMapper;
import com.tony.easymvc.mapper.ProjectBizMapper;
import com.tony.easymvc.mapper.ProjectConfigMapper;
import com.tony.easymvc.mapper.ProjectInfoMapper;
import com.tony.easymvc.mapper.ProjectTablesMapper;
import com.tony.easymvc.po.BizDb;
import com.tony.easymvc.po.BizDbExample;
import com.tony.easymvc.po.DbInfo;
import com.tony.easymvc.po.HtmlOperation;
import com.tony.easymvc.po.HtmlOperationExample;
import com.tony.easymvc.po.ProjectBiz;
import com.tony.easymvc.po.ProjectBizExample;
import com.tony.easymvc.po.ProjectConfig;
import com.tony.easymvc.po.ProjectConfigExample;
import com.tony.easymvc.po.ProjectInfo;
import com.tony.easymvc.po.ProjectTables;
import com.tony.easymvc.po.ProjectTablesExample;
import com.tony.server.JDBC;

@Service
public class ProjectService {

    @Resource
    ProjectInfoMapper   projectInfoMapper;

    @Resource
    ProjectConfigMapper projectConfigMapper;

    @Resource
    DbInfoMapper        dbInfoMapper;

    @Resource
    ProjectTablesMapper projectTablesMapper;

    @Resource
    HtmlOperationMapper htmlOperationMapper;

    @Resource
    ProjectBizMapper    projectBizMapper;

    @Resource
    BizDbMapper         bizDbMapper;

    public ProjectContext loadData(Integer id) {
        ProjectInfo pinfo = projectInfoMapper.selectByPrimaryKey(id);
        Assert.notNull(pinfo, "项目ID不存在");

        List<ProjectBiz> projectBizs = setProjectBizs(pinfo);
        pinfo.setProjectBizs(projectBizs);
        for (Iterator<ProjectBiz> iterator = projectBizs.iterator(); iterator.hasNext();) {
            ProjectBiz projectBiz = iterator.next();
            setBizDb(projectBiz);
            setBizTables(projectBiz);
        }
        ProjectContext context = budilProjectContext(pinfo);
        return context;
    }

    private List<ProjectBiz> setProjectBizs(ProjectInfo pinfo) {
        ProjectBizExample example = new ProjectBizExample();
        example.or().andProjectIdEqualTo(pinfo.getId());
        List<ProjectBiz> projectBizs = projectBizMapper.selectByExample(example);
        Assert.notEmpty(projectBizs, "没有设置数据库");
        pinfo.setProjectBizs(projectBizs);
        return projectBizs;
    }

    private void setBizTables(ProjectBiz projectBiz) {
        ProjectTablesExample pte = new ProjectTablesExample();
        pte.or().andBizIdEqualTo(projectBiz.getId());

        List<ProjectTables> tables = projectTablesMapper.selectByExample(pte);
        Assert.notNull(tables, projectBiz.getBizName() + " : 没有获取到表结构");

        for (int i = 0; i < tables.size(); i++) {
            ProjectTables pt = tables.get(i);
            HtmlOperationExample hoe = new HtmlOperationExample();
            hoe.or().andBizIdEqualTo(projectBiz.getId()).andTableNameEqualTo(pt.getTableName());
            hoe.setOrderByClause(" display_order asc");
            List<HtmlOperation> hos = htmlOperationMapper.selectByExample(hoe);
            Assert.notEmpty(hos, "配置显示属性");
            pt.setHtmlOperations(hos);
        }

        projectBiz.setProjectTables(tables);
    }

    private ProjectContext budilProjectContext(ProjectInfo pinfo) {
        ProjectContext context = new ProjectContext();
        ProjectConfigExample pce = new ProjectConfigExample();
        pce.or().andProjectIdEqualTo(pinfo.getId());
        List<ProjectConfig> pcs = projectConfigMapper.selectByExample(pce);
        pcs = pcs == null ? Lists.newArrayList() : pcs;
        context.setProjectConfigs(pcs);
        context.setProjectInfo(pinfo);
        context.setProjectBizs(pinfo.getProjectBizs());
        return context;
    }

    private void setBizDb(ProjectBiz projectBiz) {
        int bizId = projectBiz.getId();
        BizDbExample examplebd = new BizDbExample();
        examplebd.or().andBizIdEqualTo(bizId);
        List<BizDb> bizDbs = bizDbMapper.selectByExample(examplebd);

        Assert.notEmpty(bizDbs, projectBiz.getBizName() + "没有设置数据库");

        for (int i = 0; i < bizDbs.size(); i++) {
            BizDb bizdb = bizDbs.get(i);
            Assert.notNull(bizdb, "没有关联数据库");
            DbInfo dbinfo = dbInfoMapper.selectByPrimaryKey(bizdb.getDbId());
            if (bizdb.getIsMaster() == 1) {
                // 是主库
                projectBiz.setMaster(dbinfo);
            } else {
                projectBiz.setSlave(dbinfo);
            }
        }
    }

    public ProjectModel startProject(Integer id) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException, JDOMException {
        ProjectContext context = loadData(id);

        ProjectModel project = new ProjectModel();
        project.setGroupId(context.getProjectInfo().getGroupId());
        project.setArtifactId(context.getProjectInfo().getArtifactId());
        project.setVersion(context.getProjectInfo().getVersionId());
        project.setDriverClassName(context.getProjectInfo().getDriverClassName());

        project.setProjectBizs(context.getProjectBizs());

        project.setBasePath(context.getProjectInfo().getBasePath());

        project.setPix(context.getProjectInfo().getPix());
        project.setScanPackage(context.getProjectInfo().getScanPackage());
        project.setMapperPackage(context.getProjectInfo().getMapperPackage());
        project.setPoPackage(context.getProjectInfo().getPoPackage());
        project.setControllerPackage(context.getProjectInfo().getControllerPackage());
        project.setDruidUser("admin");
        project.setDruidPassword("scm123456");
        project.setMenuName(context.getProjectInfo().getMenuName());

        for (int i = 0; i < context.getProjectBizs().size(); i++) {
            ProjectBiz projectbiz = context.getProjectBizs().get(i);
            DbInfo master = projectbiz.getMaster();
            JDBC jdbc = new JDBC(context.getProjectInfo().getDriverClassName(), master.getJdbcUrl(), master.getUsername(),
                    master.getPassword());
            String dbName = TableUtils.resoleSchema(master.getJdbcUrl());
            Map<String, List<String>> cms = Maps.newHashMap();
            
            List<ProjectTables> projectTables = projectbiz.getProjectTables();
            
            for (int j = 0; j < projectTables.size(); j++) {
                ProjectTables tables = projectTables.get(j);
                String temp = tables.getTableName() + "," + tables.getObjectName();
                temp = StringUtils.isBlank(tables.getObjectName()) ? tables.getTableName() : temp;
                project.getTableNames().add(temp);

                List<String> columns = selectTextColumn(jdbc, dbName, tables.getTableName());
                cms.put(tables.getTableName(), columns);
            }
            projectbiz.setTextColumns(cms);
        }

        ProjectGenerator generator = new ProjectGenerator();
        generator.perform(project, context);
        return project;
    }

    private List<String> selectTextColumn(JDBC jdbc, String dbName, String _tableName) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        String sql = "select a.COLUMN_NAME from Information_schema.columns as a  where  a.table_Name = '" + _tableName + "' and a.table_schema='" + dbName + "' and data_type='text'";
        List<String> columns = Lists.newArrayList();
        try {
            conn = jdbc.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            try {
                while (rs.next()) {
                    columns.add(rs.getString(1));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.closeResultSet(rs);
            JdbcUtils.closeStatement(stmt);
            JdbcUtils.closeConnection(conn);
        }

        return columns;
    }

}
